home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / tnzs.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  18KB  |  751 lines

  1. /***************************************************************************
  2.  
  3.   machine.c
  4.  
  5.   Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
  6.   I/O ports)
  7.  
  8.   The I8742 MCU takes care of handling the coin inputs and the tilt switch.
  9.   To simulate this, we read the status in the interrupt handler for the main
  10.   CPU and update the counters appropriately. We also must take care of
  11.   handling the coin/credit settings ourselves.
  12.  
  13. ***************************************************************************/
  14.  
  15. #include "driver.h"
  16.  
  17. extern unsigned char *tnzs_workram;
  18.  
  19. static int mcu_type;
  20.  
  21. enum
  22. {
  23.     MCU_NONE,
  24.     MCU_EXTRMATN,
  25.     MCU_ARKANOID,
  26.     MCU_DRTOPPEL,
  27.     MCU_CHUKATAI,
  28.     MCU_TNZS
  29. };
  30.  
  31. static int mcu_initializing,mcu_coinage_init,mcu_command,mcu_readcredits;
  32. static int mcu_reportcoin;
  33. static int tnzs_workram_backup;
  34. static unsigned char mcu_coinage[4];
  35. static unsigned char mcu_coinsA,mcu_coinsB,mcu_credits;
  36.  
  37.  
  38.  
  39. READ_HANDLER( arkanoi2_sh_f000_r )
  40. {
  41.     int val;
  42.  
  43.     logerror("PC %04x: read input %04x\n", cpu_get_pc(), 0xf000 + offset);
  44.  
  45.     val = readinputport(5 + offset/2);
  46.     if (offset & 1)
  47.     {
  48.         return ((val >> 8) & 0xff);
  49.     }
  50.     else
  51.     {
  52.         return val & 0xff;
  53.     }
  54. }
  55.  
  56.  
  57. static void mcu_reset(void)
  58. {
  59.     mcu_initializing = 3;
  60.     mcu_coinage_init = 0;
  61.     mcu_coinage[0] = 1;
  62.     mcu_coinage[1] = 1;
  63.     mcu_coinage[2] = 1;
  64.     mcu_coinage[3] = 1;
  65.     mcu_coinsA = 0;
  66.     mcu_coinsB = 0;
  67.     mcu_credits = 0;
  68.     mcu_reportcoin = 0;
  69.     mcu_command = 0;
  70.     tnzs_workram_backup = -1;
  71. }
  72.  
  73. static void mcu_handle_coins(int coin)
  74. {
  75.     static int insertcoin;
  76.  
  77.     /* The coin inputs and coin counter is managed by the i8742 mcu. */
  78.     /* Here we simulate it. */
  79.     /* Chuka Taisen has a limit of 9 credits, so any */
  80.     /* coins that could push it over 9 should be rejected */
  81.     /* Coin/Play settings must also be taken into consideration */
  82.  
  83.     if (coin & 0x08)    /* tilt */
  84.         mcu_reportcoin = coin;
  85.     else if (coin && coin != insertcoin)
  86.     {
  87.         if (coin & 0x01)    /* coin A */
  88.         {
  89.             if ((mcu_type == MCU_CHUKATAI) && ((mcu_credits+mcu_coinage[1]) > 9))
  90.             {
  91.                 coin_lockout_global_w(0,1); /* Lock all coin slots */
  92.             }
  93.             else
  94.             {
  95.                 logerror("Coin dropped into slot A\n");
  96.                 coin_lockout_global_w(0,0); /* Unlock all coin slots */
  97.                 coin_counter_w(0,1); coin_counter_w(0,0); /* Count slot A */
  98.                 mcu_coinsA++;
  99.                 if (mcu_coinsA >= mcu_coinage[0])
  100.                 {
  101.                     mcu_coinsA -= mcu_coinage[0];
  102.                     mcu_credits += mcu_coinage[1];
  103.                 }
  104.             }
  105.         }
  106.         if (coin & 0x02)    /* coin B */
  107.         {
  108.             if ((mcu_type == MCU_CHUKATAI) && ((mcu_credits+mcu_coinage[3]) > 9))
  109.             {
  110.                 coin_lockout_global_w(0,1); /* Lock all coin slots */
  111.             }
  112.             else
  113.             {
  114.                 logerror("Coin dropped into slot B\n");
  115.                 coin_lockout_global_w(0,0); /* Unlock all coin slots */
  116.                 coin_counter_w(1,1); coin_counter_w(1,0); /* Count slot B */
  117.                 mcu_coinsB++;
  118.                 if (mcu_coinsB >= mcu_coinage[2])
  119.                 {
  120.                     mcu_coinsB -= mcu_coinage[2];
  121.                     mcu_credits += mcu_coinage[3];
  122.                 }
  123.             }
  124.         }
  125.         if (coin & 0x04)    /* service */
  126.         {
  127.             logerror("Coin dropped into service slot C\n");
  128.             mcu_credits++;
  129.         }
  130.         mcu_reportcoin = coin;
  131.     }
  132.     else
  133.     {
  134.         coin_lockout_global_w(0,0); /* Unlock all coin slots */
  135.         mcu_reportcoin = 0;
  136.     }
  137.     insertcoin = coin;
  138. }
  139.  
  140.  
  141.  
  142. static READ_HANDLER( mcu_arkanoi2_r )
  143. {
  144.     char *mcu_startup = "\x55\xaa\x5a";
  145.  
  146. //    logerror("PC %04x: read mcu %04x\n", cpu_get_pc(), 0xc000 + offset);
  147.  
  148.     if (offset == 0)
  149.     {
  150.         /* if the mcu has just been reset, return startup code */
  151.         if (mcu_initializing)
  152.         {
  153.             mcu_initializing--;
  154.             return mcu_startup[2 - mcu_initializing];
  155.         }
  156.  
  157.         switch (mcu_command)
  158.         {
  159.             case 0x41:
  160.                 return mcu_credits;
  161.  
  162.             case 0xc1:
  163.                 /* Read the credit counter or the inputs */
  164.                 if (mcu_readcredits == 0)
  165.                 {
  166.                     mcu_readcredits = 1;
  167.                     if (mcu_reportcoin & 0x08)
  168.                     {
  169.                         mcu_initializing = 3;
  170.                         return 0xee;    /* tilt */
  171.                     }
  172.                     else return mcu_credits;
  173.                 }
  174.                 else return readinputport(2);    /* buttons */
  175.  
  176.             default:
  177. logerror("error, unknown mcu command\n");
  178.                 /* should not happen */
  179.                 return 0xff;
  180.                 break;
  181.         }
  182.     }
  183.     else
  184.     {
  185.         /*
  186.         status bits:
  187.         0 = mcu is ready to send data (read from c000)
  188.         1 = mcu has read data (from c000)
  189.         2 = unused
  190.         3 = unused
  191.         4-7 = coin code
  192.               0 = nothing
  193.               1,2,3 = coin switch pressed
  194.               e = tilt
  195.         */
  196.         if (mcu_reportcoin & 0x08) return 0xe1;    /* tilt */
  197.         if (mcu_reportcoin & 0x01) return 0x11;    /* coin 1 (will trigger "coin inserted" sound) */
  198.         if (mcu_reportcoin & 0x02) return 0x21;    /* coin 2 (will trigger "coin inserted" sound) */
  199.         if (mcu_reportcoin & 0x04) return 0x31;    /* coin 3 (will trigger "coin inserted" sound) */
  200.         return 0x01;
  201.     }
  202. }
  203.  
  204. static WRITE_HANDLER( mcu_arkanoi2_w )
  205. {
  206.     if (offset == 0)
  207.     {
  208. //    logerror("PC %04x (re %04x): write %02x to mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), data, 0xc000 + offset);
  209.         if (mcu_command == 0x41)
  210.         {
  211.             mcu_credits = (mcu_credits + data) & 0xff;
  212.         }
  213.     }
  214.     else
  215.     {
  216.         /*
  217.         0xc1: read number of credits, then buttons
  218.         0x54+0x41: add value to number of credits
  219.         0x84: coin 1 lockout (issued only in test mode)
  220.         0x88: coin 2 lockout (issued only in test mode)
  221.         0x80: release coin lockout (issued only in test mode)
  222.         during initialization, a sequence of 4 bytes sets coin/credit settings
  223.         */
  224. //    logerror("PC %04x (re %04x): write %02x to mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), data, 0xc000 + offset);
  225.  
  226.         if (mcu_initializing)
  227.         {
  228.             /* set up coin/credit settings */
  229.             mcu_coinage[mcu_coinage_init++] = data;
  230.             if (mcu_coinage_init == 4) mcu_coinage_init = 0;    /* must not happen */
  231.         }
  232.  
  233.         if (data == 0xc1)
  234.             mcu_readcredits = 0;    /* reset input port number */
  235.  
  236.         mcu_command = data;
  237.     }
  238. }
  239.  
  240.  
  241. static READ_HANDLER( mcu_chukatai_r )
  242. {
  243.     char *mcu_startup = "\xa5\x5a\xaa";
  244.  
  245.     logerror("PC %04x (re %04x): read mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), 0xc000 + offset);
  246.  
  247.     if (offset == 0)
  248.     {
  249.         /* if the mcu has just been reset, return startup code */
  250.         if (mcu_initializing)
  251.         {
  252.             mcu_initializing--;
  253.             return mcu_startup[2 - mcu_initializing];
  254.         }
  255.  
  256.         switch (mcu_command)
  257.         {
  258.             case 0x1f:
  259.                 return (readinputport(4) >> 4) ^ 0x0f;
  260.  
  261.             case 0x03:
  262.                 return readinputport(4) & 0x0f;
  263.  
  264.             case 0x41:
  265.                 return mcu_credits;
  266.  
  267.             case 0x93:
  268.                 /* Read the credit counter or the inputs */
  269.                 if (mcu_readcredits == 0)
  270.                 {
  271.                     mcu_readcredits += 1;
  272.                     if (mcu_reportcoin & 0x08)
  273.                     {
  274.                         mcu_initializing = 3;
  275.                         return 0xee;    /* tilt */
  276.                     }
  277.                     else return mcu_credits;
  278.                 }
  279.                 /* player 1 joystick and buttons */
  280.                 if (mcu_readcredits == 1)
  281.                 {
  282.                     mcu_readcredits += 1;
  283.                     return readinputport(2);
  284.                 }
  285.                 /* player 2 joystick and buttons */
  286.                 if (mcu_readcredits == 2)
  287.                 {
  288.                     return readinputport(3);
  289.                 }
  290.  
  291.             default:
  292. logerror("error, unknown mcu command (%02x)\n",mcu_command);
  293.                 /* should not happen */
  294.                 return 0xff;
  295.                 break;
  296.         }
  297.     }
  298.     else
  299.     {
  300.         /*
  301.         status bits:
  302.         0 = mcu is ready to send data (read from c000)
  303.         1 = mcu has read data (from c000)
  304.         2 = mcu is busy
  305.         3 = unused
  306.         4-7 = coin code
  307.               0 = nothing
  308.               1,2,3 = coin switch pressed
  309.               e = tilt
  310.         */
  311.         if (mcu_reportcoin & 0x08) return 0xe1;    /* tilt */
  312.         if (mcu_reportcoin & 0x01) return 0x11;    /* coin A */
  313.         if (mcu_reportcoin & 0x02) return 0x21;    /* coin B */
  314.         if (mcu_reportcoin & 0x04) return 0x31;    /* coin C */
  315.         return 0x01;
  316.     }
  317. }
  318.  
  319. static WRITE_HANDLER( mcu_chukatai_w )
  320. {
  321.     logerror("PC %04x (re %04x): write %02x to mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), data, 0xc000 + offset);
  322.  
  323.     if (offset == 0)
  324.     {
  325.         if (mcu_command == 0x41)
  326.         {
  327.             mcu_credits = (mcu_credits + data) & 0xff;
  328.         }
  329.     }
  330.     else
  331.     {
  332.         /*
  333.         0x93: read number of credits, then joysticks/buttons
  334.         0x03: read service & tilt switches
  335.         0x1f: read coin switches
  336.         0x4f+0x41: add value to number of credits
  337.  
  338.         during initialization, a sequence of 4 bytes sets coin/credit settings
  339.         */
  340.  
  341.         if (mcu_initializing)
  342.         {
  343.             /* set up coin/credit settings */
  344.             mcu_coinage[mcu_coinage_init++] = data;
  345.             if (mcu_coinage_init == 4) mcu_coinage_init = 0;    /* must not happen */
  346.         }
  347.  
  348.         if (data == 0x93)
  349.             mcu_readcredits = 0;    /* reset input port number */
  350.  
  351.         mcu_command = data;
  352.     }
  353. }
  354.  
  355.  
  356.  
  357. static READ_HANDLER( mcu_tnzs_r )
  358. {
  359.     char *mcu_startup = "\x5a\xa5\x55";
  360.  
  361.     logerror("PC %04x (re %04x): read mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), 0xc000 + offset);
  362.  
  363.     if (offset == 0)
  364.     {
  365.         /* if the mcu has just been reset, return startup code */
  366.         if (mcu_initializing)
  367.         {
  368.             mcu_initializing--;
  369.             return mcu_startup[2 - mcu_initializing];
  370.         }
  371.  
  372.         switch (mcu_command)
  373.         {
  374.             case 0x01:
  375.                 return readinputport(2) ^ 0xff;    /* player 1 joystick + buttons */
  376.  
  377.             case 0x02:
  378.                 return readinputport(3) ^ 0xff;    /* player 2 joystick + buttons */
  379.  
  380.             case 0x1a:
  381.                 return readinputport(4) >> 4;
  382.  
  383.             case 0x21:
  384.                 return readinputport(4) & 0x0f;
  385.  
  386.             case 0x41:
  387.                 return mcu_credits;
  388.  
  389.             case 0xa0:
  390.                 /* Read the credit counter */
  391.                 if (mcu_reportcoin & 0x08)
  392.                 {
  393.                     mcu_initializing = 3;
  394.                     return 0xee;    /* tilt */
  395.                 }
  396.                 else return mcu_credits;
  397.  
  398.             case 0xa1:
  399.                 /* Read the credit counter or the inputs */
  400.                 if (mcu_readcredits == 0)
  401.                 {
  402.                     mcu_readcredits = 1;
  403.                     if (mcu_reportcoin & 0x08)
  404.                     {
  405.                         mcu_initializing = 3;
  406.                         return 0xee;    /* tilt */
  407. //                        return 0x64;    /* theres a reset input somewhere */
  408.                     }
  409.                     else return mcu_credits;
  410.                 }
  411.                 /* buttons */
  412.                 else return ((readinputport(2) & 0xf0) | (readinputport(3) >> 4)) ^ 0xff;
  413.  
  414.             default:
  415. logerror("error, unknown mcu command\n");
  416.                 /* should not happen */
  417.                 return 0xff;
  418.                 break;
  419.         }
  420.     }
  421.     else
  422.     {
  423.         /*
  424.         status bits:
  425.         0 = mcu is ready to send data (read from c000)
  426.         1 = mcu has read data (from c000)
  427.         2 = unused
  428.         3 = unused
  429.         4-7 = coin code
  430.               0 = nothing
  431.               1,2,3 = coin switch pressed
  432.               e = tilt
  433.         */
  434.         if (mcu_reportcoin & 0x08) return 0xe1;    /* tilt */
  435.         if (mcu_type == MCU_TNZS)
  436.         {
  437.             if (mcu_reportcoin & 0x01) return 0x31;    /* coin 1 (will trigger "coin inserted" sound) */
  438.             if (mcu_reportcoin & 0x02) return 0x21;    /* coin 2 (will trigger "coin inserted" sound) */
  439.             if (mcu_reportcoin & 0x04) return 0x11;    /* coin 3 (will NOT trigger "coin inserted" sound) */
  440.         }
  441.         else
  442.         {
  443.             if (mcu_reportcoin & 0x01) return 0x11;    /* coin 1 (will trigger "coin inserted" sound) */
  444.             if (mcu_reportcoin & 0x02) return 0x21;    /* coin 2 (will trigger "coin inserted" sound) */
  445.             if (mcu_reportcoin & 0x04) return 0x31;    /* coin 3 (will trigger "coin inserted" sound) */
  446.         }
  447.         return 0x01;
  448.     }
  449. }
  450.  
  451. static WRITE_HANDLER( mcu_tnzs_w )
  452. {
  453.     if (offset == 0)
  454.     {
  455.         logerror("PC %04x (re %04x): write %02x to mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), data, 0xc000 + offset);
  456.         if (mcu_command == 0x41)
  457.         {
  458.             mcu_credits = (mcu_credits + data) & 0xff;
  459.         }
  460.     }
  461.     else
  462.     {
  463.         /*
  464.         0xa0: read number of credits
  465.         0xa1: read number of credits, then buttons
  466.         0x01: read player 1 joystick + buttons
  467.         0x02: read player 2 joystick + buttons
  468.         0x1a: read coin switches
  469.         0x21: read service & tilt switches
  470.         0x4a+0x41: add value to number of credits
  471.         0x84: coin 1 lockout (issued only in test mode)
  472.         0x88: coin 2 lockout (issued only in test mode)
  473.         0x80: release coin lockout (issued only in test mode)
  474.         during initialization, a sequence of 4 bytes sets coin/credit settings
  475.         */
  476.  
  477.         logerror("PC %04x (re %04x): write %02x to mcu %04x\n", cpu_get_pc(), cpu_geturnpc(), data, 0xc000 + offset);
  478.  
  479.         if (mcu_initializing)
  480.         {
  481.             /* set up coin/credit settings */
  482.             mcu_coinage[mcu_coinage_init++] = data;
  483.             if (mcu_coinage_init == 4) mcu_coinage_init = 0;    /* must not happen */
  484.         }
  485.  
  486.         if (data == 0xa1)
  487.             mcu_readcredits = 0;    /* reset input port number */
  488.  
  489.         /* Dr Toppel decrements credits differently. So handle it */
  490.         if ((data == 0x09) && (mcu_type == MCU_DRTOPPEL))
  491.             mcu_credits = (mcu_credits - 1) & 0xff;        /* Player 1 start */
  492.         if ((data == 0x18) && (mcu_type == MCU_DRTOPPEL))
  493.             mcu_credits = (mcu_credits - 2) & 0xff;        /* Player 2 start */
  494.  
  495.         mcu_command = data;
  496.     }
  497. }
  498.  
  499.  
  500.  
  501. void init_extrmatn(void)
  502. {
  503.     unsigned char *RAM = memory_region(REGION_CPU1);
  504.  
  505.     mcu_type = MCU_EXTRMATN;
  506.  
  507.     /* there's code which falls through from the fixed ROM to bank #7, I have to */
  508.     /* copy it there otherwise the CPU bank switching support will not catch it. */
  509.     memcpy(&RAM[0x08000],&RAM[0x2c000],0x4000);
  510. }
  511.  
  512. void init_arkanoi2(void)
  513. {
  514.     unsigned char *RAM = memory_region(REGION_CPU1);
  515.  
  516.     mcu_type = MCU_ARKANOID;
  517.  
  518.     /* there's code which falls through from the fixed ROM to bank #2, I have to */
  519.     /* copy it there otherwise the CPU bank switching support will not catch it. */
  520.     memcpy(&RAM[0x08000],&RAM[0x18000],0x4000);
  521. }
  522.  
  523. void init_drtoppel(void)
  524. {
  525.     unsigned char *RAM = memory_region(REGION_CPU1);
  526.  
  527.     mcu_type = MCU_DRTOPPEL;
  528.  
  529.     /* there's code which falls through from the fixed ROM to bank #0, I have to */
  530.     /* copy it there otherwise the CPU bank switching support will not catch it. */
  531.     memcpy(&RAM[0x08000],&RAM[0x18000],0x4000);
  532. }
  533.  
  534. void init_chukatai(void)
  535. {
  536.     unsigned char *RAM = memory_region(REGION_CPU1);
  537.  
  538.     mcu_type = MCU_CHUKATAI;
  539.  
  540.     /* there's code which falls through from the fixed ROM to bank #0, I have to */
  541.     /* copy it there otherwise the CPU bank switching support will not catch it. */
  542.     memcpy(&RAM[0x08000],&RAM[0x18000],0x4000);
  543. }
  544.  
  545. void init_tnzs(void)
  546. {
  547.     unsigned char *RAM = memory_region(REGION_CPU1);
  548.     mcu_type = MCU_TNZS;
  549.  
  550.     /* there's code which falls through from the fixed ROM to bank #0, I have to */
  551.     /* copy it there otherwise the CPU bank switching support will not catch it. */
  552.     memcpy(&RAM[0x08000],&RAM[0x18000],0x4000);
  553. }
  554.  
  555. void init_insectx(void)
  556. {
  557.     mcu_type = MCU_NONE;
  558.  
  559.     /* this game has no mcu, replace the handler with plain input port handlers */
  560.     install_mem_read_handler(1, 0xc000, 0xc000, input_port_2_r );
  561.     install_mem_read_handler(1, 0xc001, 0xc001, input_port_3_r );
  562.     install_mem_read_handler(1, 0xc002, 0xc002, input_port_4_r );
  563. }
  564.  
  565. void init_kageki(void)
  566. {
  567.     /* this game has no mcu */
  568.     mcu_type = MCU_NONE;
  569. }
  570.  
  571.  
  572. READ_HANDLER( tnzs_mcu_r )
  573. {
  574.     switch (mcu_type)
  575.     {
  576.         case MCU_ARKANOID:
  577.             return mcu_arkanoi2_r(offset);
  578.             break;
  579.         case MCU_CHUKATAI:
  580.             return mcu_chukatai_r(offset);
  581.             break;
  582.         case MCU_EXTRMATN:
  583.         case MCU_DRTOPPEL:
  584.         case MCU_TNZS:
  585.         default:
  586.             return mcu_tnzs_r(offset);
  587.             break;
  588.     }
  589. }
  590.  
  591. WRITE_HANDLER( tnzs_mcu_w )
  592. {
  593.     switch (mcu_type)
  594.     {
  595.         case MCU_ARKANOID:
  596.             mcu_arkanoi2_w(offset,data);
  597.             break;
  598.         case MCU_CHUKATAI:
  599.             mcu_chukatai_w(offset,data);
  600.             break;
  601.         case MCU_EXTRMATN:
  602.         case MCU_DRTOPPEL:
  603.         case MCU_TNZS:
  604.         default:
  605.             mcu_tnzs_w(offset,data);
  606.             break;
  607.     }
  608. }
  609.  
  610. int tnzs_interrupt(void)
  611. {
  612.     int coin;
  613.  
  614.     switch (mcu_type)
  615.     {
  616.         case MCU_ARKANOID:
  617.             coin = ((readinputport(5) & 0xf000) ^ 0xd000) >> 12;
  618.             coin = (coin & 0x08) | ((coin & 0x03) << 1) | ((coin & 0x04) >> 2);
  619.             mcu_handle_coins(coin);
  620.             break;
  621.  
  622.         case MCU_EXTRMATN:
  623.         case MCU_DRTOPPEL:
  624.             coin = (((readinputport(4) & 0x30) >> 4) | ((readinputport(4) & 0x03) << 2)) ^ 0x0c;
  625.             mcu_handle_coins(coin);
  626.             break;
  627.  
  628.         case MCU_CHUKATAI:
  629.         case MCU_TNZS:
  630.             coin = (((readinputport(4) & 0x30) >> 4) | ((readinputport(4) & 0x03) << 2)) ^ 0x0f;
  631.             mcu_handle_coins(coin);
  632.             break;
  633.  
  634.         case MCU_NONE:
  635.         default:
  636.             break;
  637.     }
  638.  
  639.     return 0;
  640. }
  641.  
  642. void tnzs_init_machine (void)
  643. {
  644.     /* initialize the mcu simulation */
  645.     mcu_reset();
  646.  
  647.     /* preset the banks */
  648.     {
  649.         unsigned char *RAM;
  650.  
  651.         RAM = memory_region(REGION_CPU1);
  652.         cpu_setbank(1,&RAM[0x18000]);
  653.  
  654.         RAM = memory_region(REGION_CPU2);
  655.         cpu_setbank(2,&RAM[0x10000]);
  656.     }
  657. }
  658.  
  659.  
  660. READ_HANDLER( tnzs_workram_r )
  661. {
  662.     /* Location $EF10 workaround required to stop TNZS getting */
  663.     /* caught in and endless loop due to shared ram sync probs */
  664.  
  665.     if ((offset == 0xf10) && (mcu_type == MCU_TNZS))
  666.     {
  667.         int tnzs_cpu0_pc;
  668.  
  669.         tnzs_cpu0_pc = cpu_get_pc();
  670.         switch (tnzs_cpu0_pc)
  671.         {
  672.             case 0xc66:        /* tnzs */
  673.             case 0xc64:        /* tnzsb */
  674.             case 0xab8:        /* tnzs2 */
  675.                 tnzs_workram[offset] = (tnzs_workram_backup & 0xff);
  676.                 return tnzs_workram_backup;
  677.                 break;
  678.             default:
  679.                 break;
  680.         }
  681.     }
  682.     return tnzs_workram[offset];
  683. }
  684.  
  685. READ_HANDLER( tnzs_workram_sub_r )
  686. {
  687.     return tnzs_workram[offset];
  688. }
  689.  
  690. WRITE_HANDLER( tnzs_workram_w )
  691. {
  692.     /* Location $EF10 workaround required to stop TNZS getting */
  693.     /* caught in and endless loop due to shared ram sync probs */
  694.  
  695.     tnzs_workram_backup = -1;
  696.  
  697.     if ((offset == 0xf10) && (mcu_type == MCU_TNZS))
  698.     {
  699.         int tnzs_cpu0_pc;
  700.  
  701.         tnzs_cpu0_pc = cpu_get_pc();
  702.         switch (tnzs_cpu0_pc)
  703.         {
  704.             case 0xab5:        /* tnzs2 */
  705.                 if (cpu_getpreviouspc() == 0xab4)
  706.                     break;  /* unfortunantly tnzsb is true here too, so stop it */
  707.             case 0xc63:        /* tnzs */
  708.             case 0xc61:        /* tnzsb */
  709.                 tnzs_workram_backup = data;
  710.                 break;
  711.             default:
  712.                 break;
  713.         }
  714.     }
  715.     if (tnzs_workram_backup == -1)
  716.         tnzs_workram[offset] = data;
  717. }
  718.  
  719. WRITE_HANDLER( tnzs_workram_sub_w )
  720. {
  721.     tnzs_workram[offset] = data;
  722. }
  723.  
  724. WRITE_HANDLER( tnzs_bankswitch_w )
  725. {
  726.     unsigned char *RAM = memory_region(REGION_CPU1);
  727.  
  728.     /* bit 4 resets the second CPU */
  729.     if (data & 0x10)
  730.         cpu_set_reset_line(1,CLEAR_LINE);
  731.     else
  732.         cpu_set_reset_line(1,ASSERT_LINE);
  733.  
  734.     /* bits 0-2 select RAM/ROM bank */
  735. //    logerror("PC %04x: writing %02x to bankswitch\n", cpu_get_pc(),data);
  736.     cpu_setbank (1, &RAM[0x10000 + 0x4000 * (data & 0x07)]);
  737. }
  738.  
  739. WRITE_HANDLER( tnzs_bankswitch1_w )
  740. {
  741.     unsigned char *RAM = memory_region(REGION_CPU2);
  742.  
  743. //    logerror("PC %04x: writing %02x to bankswitch 1\n", cpu_get_pc(),data);
  744.  
  745.     /* bit 2 resets the mcu */
  746.     if (data & 0x04) mcu_reset();
  747.  
  748.     /* bits 0-1 select ROM bank */
  749.     cpu_setbank (2, &RAM[0x10000 + 0x2000 * (data & 3)]);
  750. }
  751.